#include "ipc/ipc_renderer.h"



HashMap *ipcRenderer_handler_map = NULL;  // 渲染进程事件处理器
HashMap *ipcRenderer_callback_map = NULL; // 渲染进程回调函数

// V8处理器：处理JS的ipcRenderer.on调用
static int ipc_renderer_on_handler(
    cef_v8_handler_t *self,
    const cef_string_t *name, //  被调用的 JavaScript 函数名称。用于区分处理程序绑定的多个不同函数（若支持多函数处理）
    cef_v8_value_t *object,    // JavaScript 函数调用时的 this 对象（接收者)
    size_t argumentsCount,    // 传递给函数的参数个数。用于遍历 arguments 数组时确定边界
    struct _cef_v8_value_t *const *arguments, // 指向参数值数组的指针
    cef_v8_value_t **retval,    // 输出参数，用于设置函数的返回值。若执行成功，需通过 *retval = return_value 赋值，其中
                               // return_value 是 cef_v8_value_t* 类型
    cef_string_t *exception) { // 输出参数，若执行失败，需设置异常信息字符串。例如，通过 cef_string_set 函数赋值错
    LOG_DEBUG("js on args count %d", argumentsCount);
    // 初始化哈希表
    if (!ipcRenderer_handler_map) {
        ipcRenderer_handler_map = create_hashmap();
    }

    // 参数校验：事件名 + 回调函数
    if (argumentsCount < 2 || !arguments[0]->is_string(arguments[0]) || !arguments[1]->is_function(arguments[1])) {
        cef_string_utf8_to_utf16("Invalid ipcRenderer.on arguments", 31, exception);
        return 1;
    }

    // 获取事件名和回调
    cef_string_userfree_t event_name = arguments[0]->get_string_value(arguments[0]);
    cef_v8_value_t *callback = arguments[1];
    callback->base.add_ref((cef_base_ref_counted_t *)callback);

    cef_string_utf8_t event_name_utf8 = {};
    cef_string_utf16_to_utf8(event_name->str, event_name->length, &event_name_utf8);

    // 存储到哈希表
    hashmap_insert(ipcRenderer_handler_map, event_name_utf8.str, callback);

    cef_string_userfree_free(event_name);
    cef_string_utf8_clear(&event_name_utf8);
    LOG_DEBUG("js on end");
    return 1;
}

// V8处理器：处理JS的ipcRenderer.send调用
static int ipc_renderer_send_handler(
    cef_v8_handler_t *self,
    const cef_string_t *name, //  被调用的 JavaScript 函数名称。用于区分处理程序绑定的多个不同函数（若支持多函数处理）
    cef_v8_value_t *object,    // JavaScript 函数调用时的 this 对象（接收者)
    size_t argumentsCount,    // 传递给函数的参数个数。用于遍历 arguments 数组时确定边界
    struct _cef_v8_value_t *const *arguments, // 指向参数值数组的指针
    cef_v8_value_t **retval,    // 输出参数，用于设置函数的返回值。若执行成功，需通过 *retval = return_value 赋值，其
                               // return_value 是 cef_v8_value_t* 类型
    cef_string_t *exception) { // 输出参数，若执行失败，需设置异常信息字符串。例如，通过 cef_string_set 函数赋值错
    LOG_DEBUG("js send args count %d", argumentsCount);
    // 参数校验：事件名 + 参数 + 回调
    if (argumentsCount < 1 || !arguments[0]->is_string(arguments[0]) || argumentsCount > 3) {
        cef_string_utf8_to_utf16("Invalid ipcRenderer.send arguments", 33, exception);
        return 0;
    }

    // 提取事件名
    cef_string_userfree_t event_name = arguments[0]->get_string_value(arguments[0]);

    LOG_DEBUG("js send call name: %ls", event_name->str);

    cef_string_t renderer_call_str = {};
    cef_string_utf8_to_utf16("renderer-call", strlen("renderer-call"), &renderer_call_str);
    // 构造进程消息
    cef_process_message_t *msg = cef_process_message_create(&renderer_call_str);
    cef_list_value_t *msg_args = msg->get_argument_list(msg);
    msg_args->set_size(msg_args, 3);

    msg_args->set_string(msg_args, 0, arguments[0]->get_string_value(arguments[0])); // 事件名

    // 处理参数（第二个参数)
    if (argumentsCount > 1) {
        // if (!arguments[1]->is_string(arguments[1])) {
        //     cef_string_utf8_to_utf16("Invalid ipcRenderer.send arguments", 33, exception);
        //     return 0;
        // }
        LOG_DEBUG("js send param  ");
        cef_value_t *params = ConvertV8ValueToCefValue(arguments[1]);
        msg_args->set_value(msg_args, 1, params); // 参数
        // LOG_DEBUG("js send3-2 ");
    }

    // LOG_DEBUG("js send4 ");

    msg_args->set_int(msg_args, 2, 0); // request_id  是否返回， 0 不返回， 1 返回
    // 处理第三个参数
    if (argumentsCount > 2) {
        if (!arguments[2]->is_function(arguments[2])) {
            cef_string_utf8_to_utf16("Invalid ipcRenderer.send arguments", 33, exception);
            return 0;
        }
        cef_string_utf8_t event_name_utf8 = {};
        cef_string_utf16_to_utf8(event_name->str, event_name->length, &event_name_utf8);

        if (!ipcRenderer_callback_map) {
            ipcRenderer_callback_map = create_hashmap();
        }

        cef_v8_value_t *callback = arguments[2];
        callback->base.add_ref((cef_base_ref_counted_t *)callback); // 保留引用

        hashmap_insert(ipcRenderer_callback_map, event_name_utf8.str, callback);
        msg_args->set_int(msg_args, 2, 1);

        cef_string_utf8_clear(&event_name_utf8);
    }

    // format_output_log("info", __FILE__, __LINE__, __FUNCTION__, "js send5 ");

    // 获取当前V8上下文关联的Frame
    cef_v8_context_t *context = cef_v8_context_get_current_context();
    if (!context || !context->is_valid(context)) {
        LOG_ERROR("No valid V8 context available");
        return 0;
    }
    context->enter(context);
    cef_frame_t *frame = context->get_frame(context);
    // 发送到主进程
    frame->send_process_message(frame, PID_BROWSER, msg);
    context->exit(context);

    // 释放资源
    cef_string_userfree_free(event_name);
    // msg->base.release((cef_base_ref_counted_t *)msg);
    cef_string_clear(&renderer_call_str);

    // LOG_DEBUG("js send6 ");

    return 1;
}

// 将ipcRenderer绑定到JS全局对象
void bind_ipc_renderer(cef_v8_context_t *context) {
    context->enter(context);

    cef_string_t on_str = {};
    cef_string_t send_str = {};
    cef_string_t ipc_str = {};
    cef_string_utf8_to_utf16("on", 2, &on_str);
    cef_string_utf8_to_utf16("send", 4, &send_str);
    cef_string_utf8_to_utf16("ipcRenderer", 11, &ipc_str);

    cef_v8_value_t *global = context->get_global(context);

    // 创建ipcRenderer对象
    cef_v8_value_t *ipc_renderer = cef_v8_value_create_object(NULL, NULL);

    // 绑定on处理器
    static cef_v8_handler_t on_handler;
    on_handler.base.size = sizeof(cef_v8_handler_t);
    on_handler.execute = ipc_renderer_on_handler;
    // 创建v8 函数对象
    cef_v8_value_t *on_func = cef_v8_value_create_function(&on_str,      // 函数名
                                                         &on_handler); // 关联的处理器

    // 将函数绑定到对象
    ipc_renderer->set_value_bykey(ipc_renderer,
                                  &on_str,                   // 属性名
                                  on_func,                   // 函数对象
                                  V8_PROPERTY_ATTRIBUTE_NONE // 可写、可读、可枚举、可配置
    );

    // 绑定send方法
    static cef_v8_handler_t send_handler;
    send_handler.base.size = sizeof(cef_v8_handler_t);
    send_handler.execute = ipc_renderer_send_handler;

    // 绑定send方法
    cef_v8_value_t *send_func = cef_v8_value_create_function(&send_str, // 函数名
                                                           &send_handler);

    ipc_renderer->set_value_bykey(ipc_renderer,
                                  &send_str,                 // 属性名
                                  send_func,                 // 函数对象
                                  V8_PROPERTY_ATTRIBUTE_NONE // 可写、可读、可枚举、可配置
    );

    // 挂载到全局对象
    global->set_value_bykey(global,
                            &ipc_str,                  // 属性名
                            ipc_renderer,              // 函数对象
                            V8_PROPERTY_ATTRIBUTE_NONE // 可写、可读、可枚举、可配置
    );

    // 清理字符串
    cef_string_utf16_clear(&on_str);
    cef_string_utf16_clear(&send_str);
    cef_string_utf16_clear(&ipc_str);

    context->exit(context);
}

// 处理主进程发来的消息
int handle_main_to_renderer_msg(cef_browser_t *browser, cef_frame_t *frame, cef_process_message_t *message) {
    // format_output_log("info", __FILE__, __LINE__, __FUNCTION__, "main-renderer");
    cef_string_userfree_t message_name = message->get_name(message);
    cef_string_utf16_t call = {};
    cef_string_utf8_to_utf16("main-call", strlen("main-call"), &call);
    cef_string_utf16_t callback = {};
    cef_string_utf8_to_utf16("main-response", strlen("main-response"), &callback);

    int ret_value = 0;

    // c调用, 参数解析
    cef_list_value_t *args = message->get_argument_list(message);
    cef_string_userfree_t event_name = args->get_string(args, 0);
    cef_value_t *event_data = args->get_value(args, 1);
    cef_v8_value_t *event_data_v8 = ConvertCefValueToV8Value(event_data);

    // format_output_log("info", __FILE__, __LINE__, __FUNCTION__, "main-renderer1");

    // 查找时转换CEF字符串为C字符串
    cef_string_utf8_t event_name_utf8 = {};
    cef_string_utf16_to_utf8(event_name->str, event_name->length, &event_name_utf8);

    LOG_DEBUG("main-renderer event_name=%s", event_name_utf8.str);

    if (cef_string_utf16_cmp(message_name, &call) == 0) {
        int request_id = args->get_int(args, 2);
        LOG_DEBUG("main-call request_id=%d", request_id);
        // 查找js注册函数
        cef_v8_value_t *callFunc = hashmap_get(ipcRenderer_handler_map, event_name_utf8.str);

        if (callFunc) {
            cef_v8_context_t *context = frame->get_v8_context(frame);
            context->enter(context);
            if (request_id == 0) {
                execute_js_function_single_arg(callFunc, event_data_v8);
            } else if (request_id == 1) {
                cef_v8_value_t *result = execute_js_function_single_arg(callFunc, event_data_v8);

                cef_string_t renderer_response_str = {};
                cef_string_utf8_to_utf16("renderer-response", strlen("renderer-response"), &renderer_response_str);

                cef_process_message_t *response_msg = cef_process_message_create(&renderer_response_str);
                cef_list_value_t *response_args = response_msg->get_argument_list(response_msg);
                response_args->set_size(response_args, 2);

                response_args->set_string(response_args, 0, event_name);
                response_args->set_value(response_args, 1, ConvertV8ValueToCefValue(result));

                // 获取当前V8上下文关联的Frame
                cef_v8_context_t *context = cef_v8_context_get_current_context();
                cef_frame_t *frame = context->get_frame(context);
                // 发送到主进程
                frame->send_process_message(frame, PID_BROWSER, response_msg);

                // 清理
                cef_string_clear(&renderer_response_str);
                result->base.release((cef_base_ref_counted_t *)result);
            }
            context->exit(context);
            ret_value = 1;
        }

    } else if (cef_string_utf16_cmp(message_name, &callback) == 0) {
        LOG_DEBUG("main-response ");
        // 查找js回调注册函数
        cef_v8_value_t *callbackFunc = hashmap_get(ipcRenderer_callback_map, event_name_utf8.str);

        if (!cef_currently_on(TID_RENDERER)) {
            LOG_ERROR("v8 execute_js_function_single_arg error, no TID_RENDERER");
        }

        if (callbackFunc && callbackFunc->is_function(callbackFunc)) {
            cef_v8_context_t *context = frame->get_v8_context(frame);
            if (!context || !context->is_valid(context)) {
                LOG_ERROR("No valid V8 context available");
                return 0;
            }
            context->enter(context);
            execute_js_function_single_arg(callbackFunc, event_data_v8);
            hashmap_remove(ipcRenderer_callback_map, event_name_utf8.str);
            context->exit(context);
            LOG_DEBUG("execute_js_function_single_arg end ");
        }
        ret_value = 1;
    }

    // 清理
    cef_string_clear(&call);
    cef_string_clear(&callback);
    cef_string_utf8_clear(&event_name_utf8);
    cef_string_userfree_free(event_name);
    event_data->base.release(&event_data->base);
    event_data_v8->base.release(&event_data_v8->base);
    message->base.release(&message->base);
    LOG_DEBUG("end return %d", ret_value);
    return ret_value;
}